package com.iafme.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.zhxu.bs.BeanSearcher;
import cn.zhxu.bs.operator.Contain;
import cn.zhxu.bs.operator.Equal;
import cn.zhxu.bs.util.MapUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.iafme.config.SeatNumGenerate;
import com.iafme.dto.req.OrderReqDTO;
import com.iafme.dto.res.MemberOrderResDTO;
import com.iafme.dto.res.OrderResDTO;
import com.iafme.model.Order;
import com.iafme.mapper.OrderMapper;
import com.iafme.model.Showings;
import com.iafme.properties.PayProperties;
import com.iafme.properties.ScanPayReq;
import com.iafme.service.IOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iafme.service.IShowingsService;
import com.iafme.service.OrderNoTypeService;
import com.iafme.service.RedemptionService;
import com.iafme.utils.AdmissionNumUtil;
import com.systemframework.constants.Constants;
import com.systemframework.exception.ResultException;
import com.systemframework.pay.model.PayOrderRequestDTO;
import com.systemframework.pay.service.impl.AlPay;
import com.systemframework.pay.service.impl.WxPay;
import com.systemframework.util.SearchUtl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author summer
 * @since 2025/01/05 21:14:46
 */
@Service
@AllArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    private final IShowingsService showingsService;

    private final  SeatNumGenerate seatNumGenerate;

    @Override
    public OrderResDTO updateOrderStatus(String outTradeNo) {
        LambdaQueryWrapper<Order> eq = Wrappers.lambdaQuery(Order.class).eq(Order::getOrderNo, outTradeNo);
        Order order = this.getOne(eq);
        if(order.getStatus().equals(Constants.ZERO)){
            Showings showings = showingsService.getById(order.getSessionId());
            if(showings.getAddress().equals("线上")){
                order.setSeatNum("无");
            }else{
                String s = seatNumGenerate.seatNum(showings.getId(),showings.getCity());
                order.setSeatNum(s);
            }
            order.setStatus(Constants.ONE);
            order.setAdmissionNum(AdmissionNumUtil.admissionNum());
            order.setPayTime(LocalDateTime.now());
            this.update(order,eq);
        }

        OrderResDTO orderResDTO = new OrderResDTO();
        orderResDTO.setOrderNo(order.getOrderNo());
        return orderResDTO;
    }

    @Override
    public void updateStatus(OrderReqDTO reqDTO) {
        Order order = this.getById(reqDTO.getId());
        if(ObjectUtil.isNull(order)) {
            throw new ResultException("订单不存在,操作异常");
        }
        order.setStatus(reqDTO.getStatus());
        this.updateById(order);
    }

    private final WxPay wxPay;

    private final AlPay alPay;

    private final PayProperties payProperties;

    private final RedemptionService redemptionService;

    private final OrderNoTypeService orderNoTypeService;





    @Override
    public ScanPayReq payOrder(OrderReqDTO orderReqDTO, HttpServletRequest request) {
        ScanPayReq scanPayReq = new ScanPayReq();
        Order order = this.getById(orderReqDTO.getId());
        if(ObjectUtil.isNull(order)) {
            throw new ResultException("订单不存在,操作异常");
        }
        order.setPayType(orderReqDTO.getPayType());
        String code="";
        if(orderReqDTO.getPayType().equals(3)){
            redemptionService.checkRedemption(orderReqDTO.getCode());
            this.updateById(order);
            this.updateOrderStatus(order.getOrderNo());
            scanPayReq.setCodeUrl(code);
            scanPayReq.setOrderNo(order.getOrderNo());
            return scanPayReq;

        }
            String orderNum = AdmissionNumUtil.orderNum();
            orderNoTypeService.updateOrderType(order.getOrderNo(),orderNum);
            order.setOrderNo(orderNum);
            PayOrderRequestDTO payOrderRequestDTO=new PayOrderRequestDTO();
            payOrderRequestDTO.setOrderNo(order.getOrderNo());
            payOrderRequestDTO.setProductPrice(order.getCost().toString());
            payOrderRequestDTO.setProductName(order.getDetails());
            payOrderRequestDTO.setProductId(order.getId().toString());
            if(orderReqDTO.getPayType().equals(Constants.ONE)){
                payOrderRequestDTO.setNotifyUrl(payProperties.getWxNotifyUrl());
                code=wxPay.nativePay(payOrderRequestDTO, request);
            }else if(orderReqDTO.getPayType().equals(Constants.TWO)){
                payOrderRequestDTO.setNotifyUrl(payProperties.getAliNotifyUrl());
                code=alPay.nativePay(payOrderRequestDTO, request);
            }
        this.updateById(order);
        scanPayReq.setCodeUrl(code);
        scanPayReq.setOrderNo(order.getOrderNo());
        return scanPayReq;
    }

    private final BeanSearcher beanSearcher;

    @Override
    public Page<OrderResDTO> lists(OrderReqDTO reqDTO) {
        Map<String, Object> build = MapUtils.builder().page(reqDTO.getPageNum() - 1, reqDTO.getPageSize())
                .field(OrderResDTO::getIgAasId, reqDTO.getIgAasId()).op(Contain.class)
                .field(OrderResDTO::getOrderNo, reqDTO.getOrderNo()).op(Contain.class)
                .field(OrderResDTO::getStatus, reqDTO.getStatus()).op(Equal.class)
                .field(OrderResDTO::getName, reqDTO.getName()).op(Contain.class)
                .field(OrderResDTO::getMemberId,reqDTO.getMemberId()).op(Equal.class).build();

        return SearchUtl.searchDataList(reqDTO.getPageNum(),reqDTO.getPageSize(),beanSearcher.search(OrderResDTO.class,build));
    }

    @Override
    public MemberOrderResDTO findMemberOrder(Integer orderId) {
        return this.baseMapper.findMemberOrder(orderId);
    }




}
